package com.dennytech.tac.utils;

import java.io.IOException;
import java.io.InputStream;

public class WatchedInputStream extends InputStream {
	public static interface Listener {
		void notify(int read);
	}

	public static final int DEFAULT_NOTIFY_BYTES = 0xFFF; // 4k
	private InputStream stream;
	private int remains;
	private int notifyBytes;
	private Listener listener;

	public WatchedInputStream(InputStream instream) {
		this(instream, DEFAULT_NOTIFY_BYTES);
	}

	public WatchedInputStream(InputStream instream, int notifyBytes) {
		this.stream = instream;
		this.notifyBytes = notifyBytes;
	}

	@Override
	public int available() throws IOException {
		return stream.available();
	}

	@Override
	public void close() throws IOException {
		stream.close();
	}

	@Override
	public synchronized void mark(int readlimit) {
		throw new UnsupportedOperationException();
	}

	@Override
	public boolean markSupported() {
		return false;
	}

	@Override
	public int read() throws IOException {
		int r = stream.read();
		if (r < 0 || ++remains > notifyBytes) {
			int sr = remains;
			remains = 0;
			if (listener != null)
				listener.notify(sr);
		}
		return r;
	}

	@Override
	public int read(byte[] b, int off, int len) throws IOException {
		int r = stream.read(b, off, len);
		if (r < 0) {
			int sr = remains;
			remains = 0;
			if (listener != null)
				listener.notify(sr);
			return r;
		}
		remains += r;
		if (remains > notifyBytes) {
			int sr = remains;
			remains = remains % notifyBytes;
			if (listener != null)
				listener.notify(sr - remains);
		}
		return r;
	}

	@Override
	public int read(byte[] b) throws IOException {
		return read(b, 0, b.length);
	}

	@Override
	public synchronized void reset() throws IOException {
		throw new IOException("not supported operation: reset");
	}

	@Override
	public long skip(long n) throws IOException {
		throw new IOException("not supported operation: skip");
	}

	public void setListener(Listener listener) {
		this.listener = listener;
	}
}
